/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package AccManager;

import java.io.*;
import java.util.*;

import Common.InfoLogger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
/* For DOM Comment */
import org.w3c.dom.Comment;
import org.w3c.dom.Attr;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;

//For jdk1.5 with built in xerces parser
import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

//For JDK 1.3 or JDK 1.4  with xerces 2.7.1
//import org.apache.xml.serialize.XMLSerializer;
//import org.apache.xml.serialize.OutputFormat;

/**
 *
 * @author lcy
 */
public class ServerDOMGenerator implements Runnable {
    
    /* Public data */

    /* Private data */
    List<UserProfile> gamer_list;
    private Document dom;
    private InfoLogger _debugger;
    private String _file_name;
    File _file_dp;

    public ServerDOMGenerator(){
        gamer_list = null;
        _file_name = "newEmployees.xml";
        InitCommonComponents();
    }

    public ServerDOMGenerator(List user_list, String file_name){

        gamer_list = user_list;

        if(file_name != null){
            _file_name = file_name;
        }
        else{
           _file_name =  "newEmployees.xml";
        }

        InitCommonComponents();
    }

    private void InitCommonComponents(){

        _debugger = new InfoLogger();
        _file_dp = new File(_file_name);
    }

    public void run(){
        
        createDOMTree();
        printToFile();
        _debugger.LogInfo("Generated file successfully.");
    }

    /**
     * Add a list of books to the list
     * In a production system you might populate the list from a DB
     */
    public void AddNewEntry(UserProfile new_user){

        if(gamer_list == null){
            gamer_list = new LinkedList<UserProfile>();
        }

        for(int idx = 0; idx < gamer_list.size(); idx ++){

            if(!new_user.IsBiggerThan(gamer_list.get(idx),CompareRule.NAME)){
                gamer_list.add(idx, new_user);
                return;
            }
        }

        gamer_list.add(new_user);
    }
    
    public void AddNewEntryDOM(UserProfile new_user){
        
        Element root = dom.getDocumentElement();
     
        //Name of item
        NodeList user_profile_list = root.getElementsByTagName("Gamer");

        for(int idx = 0;idx < user_profile_list.getLength();idx ++){

            Element next_item = (Element)(user_profile_list.item(idx));

            Element name_element = (Element) (next_item.getFirstChild());

            Text name_text = (Text)(name_element.getFirstChild());


            //Get the name in string;
            String text_data = name_text.getData();

            if(new_user.GetUserID().compareToIgnoreCase(text_data) <= 0){
                //Insert the node here
                Element new_element = createGamerElement(new_user);
                root.insertBefore(new_element,next_item);
                return;
            }
        }

        //Insert the node at the end here
        Element new_element = createGamerElement(new_user);
        root.appendChild(new_element);
    }

    /**
     * Using JAXP in implementation independent manner create a document object
     * using which we create a xml tree in memory
     */
    public void createDocument(List<UserProfile> cur_list) {

        if(cur_list != null){
            gamer_list = cur_list;
        }else{
            _debugger.LogInfo("DOM createDocument: arg 0 is null,stopped");
            return;
        }

        //get an instance of factory
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            //get an instance of builder
            DocumentBuilder db = dbf.newDocumentBuilder();

            //create an instance of DOM
            dom = db.newDocument();

        }catch(ParserConfigurationException pce) {
            //dump it
            _debugger.LogInfo(
                    "Error while trying to instantiate DocumentBuilder " + pce);
            System.exit(1);
        }

    }

    /**
     * The real workhorse which creates the XML structure
     */
    public void createDOMTree(){

        //create the root element <Books>
        Element rootEle = dom.createElement("UserList");
        dom.appendChild(rootEle);

        // Insert a comment in front of the element node
        Comment comment = dom.createComment("The user DataBase");
  
        rootEle.appendChild(comment);

        //No enhanced for
        Iterator it  = gamer_list.iterator();
        while(it.hasNext()) {
            UserProfile b = (UserProfile)it.next();
            //For each Book object  create <Book> element and attach it to root
            Element bookEle = createGamerElement(b);
            rootEle.appendChild(bookEle);
        }
    }

    /**
     * Helper method which creates a XML element <Gamer>
     * @param b The user profile for which we need to create an xml representation
     * @return XML element snippet representing a game player
     */
    private Element createGamerElement(UserProfile usr){

        Element bookEle = dom.createElement("Gamer");
        bookEle.setAttribute("Type", "Permanent");

        //create author element and author text node and attach it to bookElement
        Element nameEle = dom.createElement("Name");
        Text nameText = dom.createTextNode(usr.GetUserID());
        nameEle.appendChild(nameText);
        bookEle.appendChild(nameEle);

        //create title element and title text node and attach it to bookElement
        Element passEle = dom.createElement("Passwd");
        Text passText = dom.createTextNode(usr.GetPasswdRaw());
        passEle.appendChild(passText);
        bookEle.appendChild(passEle);

        //create title element and title text node and attach it to bookElement
        Element avatarEle = dom.createElement("AvatarID");
        Text avatarText = dom.createTextNode(usr.getAvatarID());
        avatarEle.appendChild(avatarText);
        bookEle.appendChild(avatarEle);

        //create title element and title text node and attach it to bookElement
        Element AlevelEle = dom.createElement("ALevel");
        Text AlevelText = dom.createTextNode((Integer.toString(usr.getAlevel())));
        AlevelEle.appendChild(AlevelText);
        bookEle.appendChild(AlevelEle);

        //create title element and title text node and attach it to bookElement
        Element DlevelEle = dom.createElement("DLevel");
        Text DlevelText = dom.createTextNode((Integer.toString(usr.getDLevel())));
        DlevelEle.appendChild(DlevelText);
        bookEle.appendChild(DlevelEle);

        //create title element and title text node and attach it to bookElement
        Element coinsEle = dom.createElement("Coins");
        Text coinsText = dom.createTextNode((Integer.toString(usr.getCoins())));
        coinsEle.appendChild(coinsText);
        bookEle.appendChild(coinsEle);

         //create title element and title text node and attach it to bookElement
        Element expEle = dom.createElement("Exp");
        Text expText = dom.createTextNode((Integer.toString(usr.getExp())));
        expEle.appendChild(expText);
        bookEle.appendChild(expEle);

        Element mpEle = dom.createElement("MP");
        Text mpText = dom.createTextNode((Integer.toString(usr.GetMagicPoint())));
        mpEle.appendChild(mpText);
        bookEle.appendChild(mpEle);

        Element capaEle = dom.createElement("Capa");
        String value = CreateCapaValue(usr.getCapaList());
        Text capaText = dom.createTextNode(value);
        capaEle.appendChild(capaText);
        bookEle.appendChild(capaEle);

        Element genderEle = dom.createElement("Gender");
        Text genderText = dom.createTextNode((Integer.toString(usr.getGender())));
        genderEle.appendChild(genderText);
        bookEle.appendChild(genderEle);

        Element statusEle = dom.createElement("Status");
        String statusValue = "offline";//CreateStatusValue(usr.GetUserStatus());
        Text statusText = dom.createTextNode(statusValue);
        statusEle.appendChild(statusText);
        bookEle.appendChild(statusEle);

        
        Element contactEle = dom.createElement("Contact");
        String contactValue = CreateContactValue(usr.GetContactList());
        Text contactText = dom.createTextNode(contactValue);
        contactEle.appendChild(contactText);
        bookEle.appendChild(contactEle);
        
        
        return bookEle;

    }

    private String CreateContactValue(ArrayList<String> contactList){
        String ret = "";

        if(contactList != null && contactList.size() > 0){
            ret += contactList.get(0);
            for(int i = 1; i < contactList.size(); i ++){
                ret += ",";
                ret += contactList.get(i);
            }
        }

        return ret;
        
    }

    private String CreateStatusValue(UserStatus status){
        String ret="";

        switch(status){
            case OFFLINE:
                ret = "offline";
                break;
            case ONLINE:
                ret = "online";
                break;
            case INGAME:
                ret = "ingame";
                break;
        }
        return ret;
    }

    private String CreateCapaValue(int [] capaList){

        String ret = "";
        if(capaList != null){
            ret += Integer.toString(capaList[0]);
            for(int i = 1; i < capaList.length; i ++){
                ret += ",";
                ret += Integer.toString(capaList[0]);
            }
        
        }
        
        return ret;
    }

    /**
     * This method uses Xerces specific classes
     * prints the XML document to file.
     */
    public void printToFile(){

        try
        {
            //print
            OutputFormat format = new OutputFormat(dom);
            format.setIndenting(true);

            //to generate output to console use this serializer
            //XMLSerializer serializer = new XMLSerializer(System.out, format);


            //to generate a file output use fileoutputstream instead of system.out
            XMLSerializer serializer = new XMLSerializer(
            new FileOutputStream(new File(_file_name)), format);

            serializer.serialize(dom);

        } catch(IOException ie) {
            ie.printStackTrace();
        }
    }
}
